﻿using System.Collections.Generic;
using System;
using System.Text;

namespace DevOnServer
{
    public class CPacket
    {
        public void addItem(CItem item)
        {
            addInt(item.Prop.ID);
            addInt(0);
            addInt(0);
            addShort((short)item.Count);

            addByte(0);
            addInt(0);
            addInt(0);
            addByte(0);
            addInt(0);
            addInt(0);
            addByte(0);
            addInt(0);
            addInt(0);
            addInt(0);
            addInt(0);
            addInt(0);
            addLong(0);
            addLong(0);
            addByte(0);
            addInt(0);
        }

        public void addBytes(byte[] bytes, int count)
        {
            for (int i = 0; i < count; i++)
                m_content.Add(bytes[i]);
        }

        public void addByte(byte b)
        {
            m_content.Add(b);
        }

        public void addInt(int i)
        {
            addBytes(BitConverter.GetBytes(i), 4);
        }

        public void addShort(short s)
        {
            addBytes(BitConverter.GetBytes(s), 2);
        }

        public void addUShort(ushort s)
        {
            addBytes(BitConverter.GetBytes(s), 2);
        }

        public void addString(string s)
        {
            addInt(s.Length);
            addBytes(Encoding.Default.GetBytes(s), s.Length);
        }

        public void addFloat(float f)
        {
            addBytes(BitConverter.GetBytes(f), 4);
        }

        public void addDouble(double d)
        {
            addBytes(BitConverter.GetBytes(d), 8);
        }

        public void addPosition(CVec3Df pos)
        {
            addFloat(pos.X);
            addFloat(pos.Y);
            addFloat(pos.Z);
        }

        public void addLong(long l)
        {
            addBytes(BitConverter.GetBytes(l), 8);
        }

        public void setInt(int pos, int i)
        {
            byte[] bytes = BitConverter.GetBytes(i);

            m_content[pos++] = bytes[0];
            m_content[pos++] = bytes[1];
            m_content[pos++] = bytes[2];
            m_content[pos] = bytes[3];
        }

        public void setShort(int pos, short s)
        {
            byte[] bytes = BitConverter.GetBytes(s);

            m_content[pos++] = bytes[0];
            m_content[pos] = bytes[1];
        }

        public short getShort(int pos)
        {
            int oldReadingPos = m_readingPos;
            m_readingPos = pos;

            short result = readShort();

            m_readingPos = oldReadingPos;
            return result;
        }

        public byte readByte()
        {
            if (m_readingPos < m_content.Count)
                return m_content[m_readingPos++];
            else
                return 0;
        }

        public int readInt()
        {
            if (m_readingPos + 3 < m_content.Count)
            {
                byte[] bytes = new byte[4];

                bytes[0] = m_content[m_readingPos++];
                bytes[1] = m_content[m_readingPos++];
                bytes[2] = m_content[m_readingPos++];
                bytes[3] = m_content[m_readingPos++];

                return BitConverter.ToInt32(bytes, 0);
            }
            else
                return 0;
        }

        public long readLong()
        {
            if (m_readingPos + 7 < m_content.Count)
            {
                byte[] bytes = new byte[8];

                bytes[0] = m_content[m_readingPos++];
                bytes[1] = m_content[m_readingPos++];
                bytes[2] = m_content[m_readingPos++];
                bytes[3] = m_content[m_readingPos++];
                bytes[4] = m_content[m_readingPos++];
                bytes[5] = m_content[m_readingPos++];
                bytes[6] = m_content[m_readingPos++];
                bytes[7] = m_content[m_readingPos++];

                return BitConverter.ToInt64(bytes, 0);
            }
            else
                return 0;
        }

        public float readFloat()
        {
            if (m_readingPos + 3 < m_content.Count)
            {
                byte[] bytes = new byte[4];

                bytes[0] = m_content[m_readingPos++];
                bytes[1] = m_content[m_readingPos++];
                bytes[2] = m_content[m_readingPos++];
                bytes[3] = m_content[m_readingPos++];

                return BitConverter.ToSingle(bytes, 0);
            }
            else
                return 0f;
        }

        public CVec3Df readPosition()
        {
            return new CVec3Df(readFloat(), readFloat(), readFloat());
        }

        public short readShort()
        {
            if (m_readingPos + 2 < m_content.Count)
            {
                byte[] bytes = new byte[2];

                bytes[0] = m_content[m_readingPos++];
                bytes[1] = m_content[m_readingPos];

                return BitConverter.ToInt16(bytes, 0);
            }
            else
                return 0;
        }

        public string readString()
        {
            int lenght = readInt();
            if (lenght > 0)
            {
                byte[] bytes = new byte[lenght];
                m_content.CopyTo(m_readingPos, bytes, 0, lenght);
                m_readingPos += lenght;
                return Encoding.Default.GetString(bytes);
            }
            else
                return "";
        }

        public void move(int move)
        {
            m_readingPos += move;

            if (m_readingPos < 0)
                m_readingPos = 0;
            else if (m_readingPos >= m_content.Count)
                m_readingPos = m_content.Count - 1;
        }

        public void clear()
        {
            m_content.Clear();
            m_readingPos = 0;
        }

        public int Lenght
        {
            get
            {
                return m_content.Count;
            }
        }

        public byte[] Data
        {
            get
            {
                return m_content.ToArray();
            }
        }

        public bool End
        {
            get
            {
                return m_readingPos + 1 >= m_content.Count;
            }
        }

        private List<byte> m_content = new List<byte>(512);

        private int m_readingPos = 0;
    }
}